#include "actioninput.h"
#include <QtGui>
#include <QtCore>
#include <QApplication>
#include <Windows.h>


ActionInput::ActionInput(QString text, bool paste)
{
    classname = __FUNCTION__;
    actParam = QJsonObject();
    actParam.insert("text",text);
    actParam.insert("paste",paste?1:0);
}

int ActionInput::execute()
{
    QString text = actParam.value("text").toString();
    bool paste = (actParam.value("paste").toInt()==1);
    qInfo()<<classname<<"input text"<<text<<"isPaste"<<paste;
    if(text.isEmpty()){
        message = "input text is empty.";
        return -1;
    }

    if(paste)
    {
        INPUT input[4];
        memset(input,0,sizeof(INPUT)*4);
        int inputIndex = 0;
        DWORD timestamp = 1;
        QClipboard *cb = QApplication::clipboard();
        QString oldText = cb->text();
        qDebug()<<"clipboard old"<<oldText;
        cb->setText(text);
        QThread::msleep(50);

        input[inputIndex].type = INPUT_KEYBOARD;
        input[inputIndex].ki.dwFlags = 0;
        input[inputIndex].ki.wVk = VK_CONTROL;
        input[inputIndex].ki.time = timestamp;
        ++inputIndex; timestamp+=10;

        input[inputIndex].type = INPUT_KEYBOARD;
        input[inputIndex].ki.dwFlags = 0;
        input[inputIndex].ki.wVk = 'V';  //'V'
        input[inputIndex].ki.time = timestamp;
        ++inputIndex; timestamp+=10;

        input[inputIndex].type = INPUT_KEYBOARD;
        input[inputIndex].ki.dwFlags = KEYEVENTF_KEYUP;
        input[inputIndex].ki.wVk = 'V';  //'V'
        input[inputIndex].ki.time = timestamp;
        ++inputIndex; timestamp+=10;

        input[inputIndex].type = INPUT_KEYBOARD;
        input[inputIndex].ki.dwFlags = KEYEVENTF_KEYUP;
        input[inputIndex].ki.wVk = VK_CONTROL;
        input[inputIndex].ki.time = timestamp;
        ++inputIndex; timestamp+=10;

        ::SendInput(inputIndex,input,sizeof(INPUT));

        //稍作等待，把原剪贴板恢复.
        //for(int w=0;w<inputIndex;w++)
        //{
            QThread::msleep(500);
        //    QApplication::processEvents();
       // }
        cb->setText(oldText);
        return 0;
    }
    else
    {
        return charecterInput(text);
    }

    Q_ASSERT(false);
    return -1;
}

//VK_ADD~~VK_OEM_PLUS     VK_MULTIPLY~~shift+8
static const uint8_t AscVk[128] = {  //asc码对应的VK（基础）码.
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    VK_SPACE, '1', VK_OEM_7, '3', '4', '5', '7', VK_OEM_7, '9', '0', VK_MULTIPLY, VK_ADD, VK_OEM_COMMA, VK_OEM_MINUS, VK_OEM_PERIOD, VK_OEM_2,  //空格到斜杠
    '0','1','2','3','4','5','6','7','8','9',VK_OEM_1,VK_OEM_1,VK_OEM_COMMA,VK_OEM_PLUS,VK_OEM_PERIOD,VK_OEM_2,
    '2', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', VK_OEM_4,VK_OEM_5,VK_OEM_6,'6',VK_OEM_MINUS,
    VK_OEM_3,'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', VK_OEM_4,VK_OEM_5,VK_OEM_6,VK_OEM_3,0
};
static const uint8_t ShfMk[128] = {  //asc码对应，标记是否要shift
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0
};

//考虑兼容性最佳，使用按键老老实实.
int ActionInput::charecterInput(QString text)
{
    QByteArray txt = text.toLocal8Bit();
    if(txt.length()>64){
        message = "text too long, <=64";
        return -1;
    }

    const int maxCount = txt.length()*4;
    INPUT *inputs = new INPUT[maxCount];
    memset(inputs,0,sizeof(INPUT)*maxCount);
    int inputIndex = 0;
    DWORD timestamp = 1;
    for(int i=0;i<txt.length();i++)
    {
        char c = txt.at(i);
        uint8_t vk = AscVk[c];
        if(vk == 0){
            message = text + "invalid char";
            return -1;
        }

        if(ShfMk[c])
        {
            inputs[inputIndex].type = INPUT_KEYBOARD;
            inputs[inputIndex].ki.dwFlags = 0;
            inputs[inputIndex].ki.wVk = VK_SHIFT;
            inputs[inputIndex].ki.time = timestamp;
            ++inputIndex; timestamp+=10;
        }

        inputs[inputIndex].type = INPUT_KEYBOARD;
        inputs[inputIndex].ki.dwFlags = 0;
        inputs[inputIndex].ki.wVk = vk;
        inputs[inputIndex].ki.time = timestamp;
        ++inputIndex; timestamp+=10;

        inputs[inputIndex].type = INPUT_KEYBOARD;
        inputs[inputIndex].ki.dwFlags = KEYEVENTF_KEYUP;
        inputs[inputIndex].ki.wVk = vk;
        inputs[inputIndex].ki.time = timestamp;
        ++inputIndex; timestamp+=10;

        if(ShfMk[c])
        {
            inputs[inputIndex].type = INPUT_KEYBOARD;
            inputs[inputIndex].ki.dwFlags = KEYEVENTF_KEYUP;
            inputs[inputIndex].ki.wVk = VK_SHIFT;
            inputs[inputIndex].ki.time = timestamp;
            ++inputIndex; timestamp+=10;
        }
    }
    ::SendInput(inputIndex,inputs,sizeof(INPUT));

    //for(int w=0;w<inputIndex;w++)
    //{
    //qDebug()<<"tick"<<GetTickCount();
    QThread::msleep(500);
    //QApplication::processEvents();
    //}

    delete[] inputs;

    return 0;
}
